package com.example.ws;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.domain.Friend;
import com.example.domain.User;
import com.example.result.Message;
import com.example.result.UserResult;
import com.example.result.msgResult;
import com.example.result.offMsgData;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Component
@ServerEndpoint(value = "/chat",configurator = GetHttpSessionConfigurator.class)  //configurator关联GetHttpSessionConfigurator类
public class WebSocketServer {

    //用来存储每一个客户端对象对应的chatEndpoint对象
    private static Map<String,WebSocketServer> onlineUsers=new ConcurrentHashMap<>();
    //声明session对象，通过该对象可以发送消息给指定的对象
    private Session session;
    //声明一个HttpSession对象，我们之在HttpSession对象中存储了用户名
    private HttpSession httpSession;
    //关闭连接时的名称
    private String adminName;
    //当对方离线时的消息存储
    private static List<offMsgData> offlineList=new CopyOnWriteArrayList<>();

    @OnOpen  //连接建立时被调用
    public void onOpen(Session session, EndpointConfig config){
        //将局部的session对象赋值给成员session
        this.session=session;
        //获取httpSession对象
        this.httpSession=(HttpSession)config.getUserProperties().get(HttpSession.class.getName());

        //从httpSession对象中获取用户名
        UserResult userResult=(UserResult)httpSession.getAttribute("user");
        adminName=userResult.getUsername();
        //将当前对象存储到在客户端容器中
        onlineUsers.put(userResult.getUsername(),this);

        //获取消息，将消息转换为json
        String json = JSONUtil.toJsonStr(new msgResult(0,null,onlineUsers.keySet()));
        //调用方法进行系统消息的推送
        broadcastAllUser(json);

        //当我上线时,接受来自对方的消息
        offsendUser(userResult.getUsername());

    }
    //推送所有客户端消息
    private void broadcastAllUser(String message){
        try {
            //获取当前在线用户的用户名
            Set<String> names = onlineUsers.keySet();
            for (String name : names) {
                //发送给客户端
                onlineUsers.get(name).session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //当我上线时,接受来自对方的消息
    private void offsendUser(String toName){
        //外key为接受者，内key为发送者
        try {
            for (int index=0;index<offlineList.size();index++) {
                if(offlineList.get(index).getToName().equals(toName)){
                    onlineUsers.get(toName).session.getBasicRemote().sendText(offlineList.get(index).getMessage());
                    offlineList.remove(index);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnMessage  //接收到客户端发送的数据时被调用
    public void OnMessage(String message,Session session){
        //将json字符串转换为对象
        Message msg = JSONUtil.toBean(message, Message.class);
        //获取当前登录的用户
        UserResult userResult=(UserResult)httpSession.getAttribute("user");
        //转换为发送的消息格式
        String json =null;
        if(msg.getIs_add()){
            json = JSONUtil.toJsonStr(new msgResult(2,userResult.getUsername(),msg.getMessage()));
        }else{
            json = JSONUtil.toJsonStr(new msgResult(1,userResult.getUsername(),msg.getMessage()));
            //存储对方离线数据
            if(onlineUsers.get(msg.getToName())==null){
                offlineList.add(new offMsgData(userResult.getUsername(),msg.getToName(),json));
                return;
            }
        }
        try {
            onlineUsers.get(msg.getToName()).session.getBasicRemote().sendText(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @OnClose  //当会话关闭时调用
    public void OnClose(Session session){
        //获取当前登录的用户

        //从容器中删除指定的用户
        onlineUsers.remove(adminName);
        adminName=null;
        //获取推送的消息
        String json = JSONUtil.toJsonStr(new msgResult(0,null,onlineUsers.keySet()));
        System.out.println(json);
        broadcastAllUser(json);
    }
}
